<?php
class Cron {
	public function add() {
	
	}
	
	public function edit() {
	
	}
	
	public function del() {
	
	}
	
	public function get() {
	
	}
	
	public function run() {
		try {
			error_reporting ( 0 );
			set_time_limit ( 0 );
			$sPath = Base::getConf ( 'cron.path' );
			if ($sPath == null) {
				if (! realpath ( ROOT . '/cron' )) {
					throw new ExceptionExt ( '计划任务目录' . $sPath . '不存在' );
				} else {
					$sPath = ROOT . '/cron';
				}
			} elseif (! realpath ( $sPath )) {
				if (! realpath ( ROOT . '/' . $sPath )) {
					throw new ExceptionExt ( '计划任务目录' . $sPath . '不存在' );
				} else {
					$sPath = ROOT . '/cron';
				}
			}
			
			$sSql = 'SELECT * FROM `cron` WHERE `status` = "active" AND `run` <= UNIX_TIMESTAMP()';
			Base::$oBase->Db_query ( $sSql );
			while ( $aRow = Base::$oBase->Db_getRow () ) {
				if (is_file ( $sPath . '/' . $aRow ['shell'] )) {
					$iAfterRunTime = self::_getAfterRunTime ( $aRow ['minute'], $aRow ['hour'], $aRow ['day'], $aRow ['month'], $aRow ['week'] );
					$sSql = 'UPDATE `cron` SET `run`= ? WHERE id = ?';
					Base::$oBase->Db_exec ( $sSql, array ($iAfterRunTime, $aRow ['id'] ) );
					error_log ( date ( 'Y-m-d H:i:s' ) . "\t" . $aRow ['shell'] . "\t" . 'succeed' . "\n", 3, 'cron.log' );
					require_once $sPath . '/' . $aRow ['shell'];
				} else {
					error_log ( date ( 'Y-m-d H:i:s' ) . "\t" . $aRow ['shell'] . "\t" . 'fail' . "\n", 3, 'cron.log' );
				}
			}
			sleep ( 60 );
			self::run ();
		} catch ( ExceptionExt $e ) {
			$e->showError ();
		}
	}
	
	private function _getAfterRunTime($iMinute, $iHour, $iDay, $iMonth, $iWeek) {
		if ($iMinute == '*') {
			return time () + 60;
		}
		
		if ($iHour == '*' && $iMinute == '*') {
			return time () + 3600;
		}
		
		if ($iDay == '*' && $iHour == '*' && $iMinute == '*') {
			return time () + 86400;
		}
		
		if ($iMonth == '*' && $iWeek == '*' && $iDay == '*' && $iHour == '*' && $iMinute == '*') {
			return time () + 86400 * date ( 't' );
		}
		
		$aTime = array (time () );
		if ($iWeek != '*') {
			$aTime = self::_getTime ( $iWeek, date ( 'w' ), 86400, 7, $aTime );
		} elseif ($iDay != '*') {
			$aTime = array ();
			$aDay = explode ( ',', $iDay );
			if ($iMonth != '*') {
				$aMonth = explode ( ',', $iMonth );
				foreach ( $aDay as $iDay ) {
					foreach ( $aMonth as $iMonth ) {
						$aTime [] = strtotime ( date ( 'Y-' ) . $iMonth . '-' . $iDay . ' ' . date ( 'H:i:s' ) );
						$aTime [] = strtotime ( (date ( 'Y' ) + 1) . '-' . $iMonth . '-' . $iDay . ' ' . date ( 'H:i:s' ) );
					}
				}
			} else {
				foreach ( $aDay as $iDay ) {
					$aTime [] = strtotime ( date ( 'Y-m' ) . '-' . $iDay . ' ' . date ( 'H:i:s' ) );
					if (date ( 'm' ) == 12) {
						$iYear = date ( 'Y' ) + 1;
						$aTime [] = strtotime ( $iYear . date ( '-m-' ) . $iDay . ' ' . date ( 'H:i:s' ) );
					} else {
						$aTime [] = strtotime ( date ( 'Y-m-' ) . $iDay . ' ' . date ( 'H:i:s' ) );
					}
				}
			}
		}
		
		if ($iHour != '*') {
			$aTime = self::_getTime ( $iHour, date ( 'G' ), 3600, 24, $aTime );
		}
		$aTime = self::_getTime ( $iMinute, intval ( date ( 'i' ) ), 60, 60, $aTime );
		sort ( $aTime );
		foreach ( $aTime as $iTime ) {
			if ($iTime > time ()) {
				return $iTime;
			}
		}
	}
	
	private function _getTime($sDate, $iNowDate, $iSecond, $iMax, $aTime = array()) {
		$aDate = explode ( ',', $sDate );
		foreach ( $aDate as $sRow ) {
			foreach ( $aTime as $iTime ) {
				$aResult [] = $iTime + ($sRow - $iNowDate) * $iSecond;
				if (count ( $aTime ) == 1) {
					$aResult [] = $iTime + ($sRow - $iNowDate + $iMax) * $iSecond;
				}
			}
		}
		return $aResult;
	}
}